package com.niiwoo.civet.mobile.controller;

import java.util.List;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.niiwoo.civet.trade.dto.request.CreditAuditBackRequestDTO;
import com.niiwoo.civet.trade.enums.ProjectTypeEnum;
import com.niiwoo.civet.trade.service.loan.ConsumeLoanDubboService;
import com.niiwoo.civet.trade.service.loan.CreditCardLoanDubboService;
import com.niiwoo.civet.trade.service.loan.SmallLoanDubboService;
import com.niiwoo.civet.trade.service.loan.SocialSecurityLoanDubboService;
import com.niiwoo.tripod.tiancheng.enums.AgainstFakeErrorCodeEnum;
import com.niiwoo.tripod.tiancheng.request.afp.AgainstFakeModelV2CallbackRequest;
import com.niiwoo.tripod.tiancheng.request.afp.AgainstFakeModelV2CallbackRequest.BoolRule;
import com.niiwoo.tripod.tiancheng.request.afp.AgainstFakeModelV2CallbackRequest.BoolRuleData;
import com.niiwoo.tripod.tiancheng.request.common.AgainstFakeBaseRequest;
import com.niiwoo.tripod.tiancheng.response.common.AgainstFakeV2Response;
import com.niiwoo.tripod.web.annotation.AuthIgnore;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;

/**
 * @Description: 天秤回调地址
 * @Author:zhoulinquan
 * @Date:2018/4/21
 */
@Slf4j
@AuthIgnore
@RestController
@RequestMapping("/tc/v2")
@Api(tags = "V5.1.5 天秤回调", description = "/tc/v2")
public class TianchengV2CallbackController {

	@Reference(version = "1.0.0")
	private SmallLoanDubboService smallLoanDubboService;

	@Reference(version = "1.0.0")
	private SocialSecurityLoanDubboService socialSecurityLoanDubboService;

	@Reference(version = "1.0.0")
	private CreditCardLoanDubboService creditCardLoanDubboService;
	
	@Reference(version = "1.0.0")
	private ConsumeLoanDubboService comsumeLoanDubboService;
	
	//只考虑命中数据
	private static final String hits = "命中";
	private static final String auditPointstSep = ";"; 
	//数据库命中结果字段存储长度
	private static final int auditPointstLen = 512 / 3; //数据库varchar长度/3(字符集为utf8)

	/**
	 * 天秤信审回调
	 */
	@ApiOperation("V5.1.5 天秤信审回调")
	@RequestMapping(value = "/auditPointFake/{projectId}/{projectType}/callback", produces = "text/plain;charset=utf-8")
	public String againstFakeV2Callback(@PathVariable(name = "projectId") Long projectId,
			@PathVariable(name = "projectType") Byte projectType,
			@RequestBody AgainstFakeBaseRequest againstFakeBaseRequest) {

		AgainstFakeV2Response againstFakeV2Response = new AgainstFakeV2Response();
		againstFakeV2Response.setSession_id(againstFakeBaseRequest.getSession_id());
		againstFakeV2Response.setVersion(againstFakeBaseRequest.getVersion());

		CreditAuditBackRequestDTO request = parseTianchengRequestParams(projectId, projectType, againstFakeBaseRequest);
		if (request == null || request.getDecision() == null || request.getStatus() == null) {
			log.error("异常信审回调参数={}", JSONObject.toJSONString(againstFakeBaseRequest));
			againstFakeV2Response.setCode(AgainstFakeErrorCodeEnum.PRAM_ERROR.getErrorCode());
			againstFakeV2Response.setCode_desc("failure");
			return JSON.toJSONString(againstFakeV2Response);
		}

		// 调用信审回调接口
		ProjectTypeEnum pt = ProjectTypeEnum.getEnum(projectType);
		switch (pt) {
		case SMALL_LOAN: // 小易贷
			RpcContext.getContext().asyncCall(() -> smallLoanDubboService.tianchengCreditAuditCallback(request));
			break;
		case SOCIAL_SECURITY_LOAN: // 社保贷
			RpcContext.getContext().asyncCall(() -> socialSecurityLoanDubboService.tianchengCreditAuditCallback(request));
			break;
		case CREDIT_CARD_LOAN: // 信用卡贷
			RpcContext.getContext().asyncCall(() -> creditCardLoanDubboService.tianchengCreditAuditCallback(request));
			break;
		case CONSUME_LOAN: // 信用卡贷
			RpcContext.getContext().asyncCall(() -> comsumeLoanDubboService.tianchengCreditAuditCallback(request));
			break;			
		default:
			log.error("异常天秤信审回调信息={}", JSONObject.toJSONString(againstFakeBaseRequest));
		}
		
		// 返回成功
		againstFakeV2Response.setCode(AgainstFakeErrorCodeEnum.SUCCESS.getErrorCode());
		againstFakeV2Response.setCode_desc("success");
		return JSON.toJSONString(againstFakeV2Response);
	}

	private CreditAuditBackRequestDTO parseTianchengRequestParams(Long projectId, Byte projectType,
			AgainstFakeBaseRequest againstFakeBaseRequest) {
		if (againstFakeBaseRequest == null || againstFakeBaseRequest.getMsg_body() == null)
			return null;

		String msgBody = JSON.toJSONString(againstFakeBaseRequest.getMsg_body());
		AgainstFakeModelV2CallbackRequest againstFakeModelV2CallbackRequest = new AgainstFakeModelV2CallbackRequest();
		try {
			JSONObject msgBodyJSON = JSONObject.parseObject(msgBody);
			if (msgBodyJSON == null) return null; 
			
			againstFakeModelV2CallbackRequest = msgBodyJSON.toJavaObject(AgainstFakeModelV2CallbackRequest.class);
		} catch (Exception ex) {
			return null;
		}

		if (againstFakeModelV2CallbackRequest.getResult() == null)
			return null;

		CreditAuditBackRequestDTO request = new CreditAuditBackRequestDTO();
		request.setProjectType(projectType);
		request.setProjectId(projectId);
		request.setFlowId(Long.valueOf(againstFakeBaseRequest.getReserve()));
		request.setStatus(againstFakeModelV2CallbackRequest.getStatus());
		request.setDecision(againstFakeModelV2CallbackRequest.getResult().getDecision());
		
		request.setAuditResult(request.getDecision().byteValue());
		
		request.setAuditPoints(request.buildAuditPoints());
		
		List<BoolRule> bool_rules = againstFakeModelV2CallbackRequest.getResult().getDetail().getBool_rules();
		if (bool_rules == null || bool_rules.isEmpty()) return request;
		
		List<BoolRuleData> boolRuleDataList = null;
		StringBuffer buf = new StringBuffer();
		for (BoolRule boolRule : bool_rules) {
			if (!hits.equals(boolRule.getHit())) continue;
			
			boolRuleDataList = boolRule.getData();
			if (boolRuleDataList == null || boolRuleDataList.isEmpty()) continue;
			
			for (BoolRuleData boolRuleData : boolRuleDataList) {
				if (!hits.equals(boolRuleData.getHit())) continue;
				
				if ("".equals(buf.toString())) {
					buf.append(boolRuleData.getCellrule_name());
				} else {
					buf.append(auditPointstSep).append(boolRuleData.getCellrule_name());
				}
			}
		}
		if (buf.length() < auditPointstLen && !"".equals(buf.toString())) request.setAuditPoints(buf.toString()); 
		
		return request;
	}
}
